home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 November / Macworld (1999-11).dmg / Updaters / WhiteCap 3.0.4 / WhiteCap Source.sit / WhiteCap Source / Common / General Tools / Headers / nodeClass.h < prev    next >
Text File  |  1999-07-13  |  12KB  |  312 lines

  1.  
  2. #ifndef _NODECLASS_
  3. #define _NODECLASS_
  4.  
  5. #ifndef NULL
  6. #define NULL 0L
  7. #endif
  8.  
  9. class nodeClass;
  10. class CEgIStream;
  11. class CEgOStream;
  12.  
  13. //#define EG_DEBUG
  14.  
  15. enum {
  16.     nodeClassT                = 1,
  17.     entryClassT                = 2,
  18.     CEgDbMgrT                = 4,
  19.     CEgChapMgrT                = 5,
  20.     CPLDbMgrT                = 6,
  21.     FdeT                    = 7,
  22.     FqpT                    = 8,
  23.     FAttributeT                = 9,
  24.     FParagraphT                = 10,
  25.     FBitmapT                = 11,
  26.     CDbItemRefNodeT            = 12,
  27.     CStrNodeT                = 13,
  28.     nodeClassReserved        = 14,
  29.     FTabT                    = 15,
  30.     FFractionT                = 16,
  31.     FVerticalSubT            = 17,
  32.     CPLItemT                = 90,
  33.  
  34.     cEgSubEnd                = 0
  35. };
  36.  
  37.  
  38. //    Use this macro to register your derived node class with nodeClass
  39. #define    RegisterNode_( ClassName ) TNodeRegistrar<ClassName>::RegisterNode( ClassName##T );
  40.  
  41. typedef nodeClass*    (*CreatorFuncT)( nodeClass* inParent );
  42.  
  43. #define isPLItem( nodePtr )                (( nodePtr -> GetType() == 90 ) ? (CPLItem*) nodePtr : NULL)
  44. #define Cast( nodePtr, className )        (( nodePtr -> GetType() == className##T ) ? (className*) nodePtr : NULL)
  45.  
  46.  
  47.  
  48. /*    This is a basic list classn.  Derive from nodeClass and attach you data
  49. */
  50.  
  51.  
  52. class nodeClass {
  53.  
  54.     friend class XList;
  55.     
  56.     private:
  57.         static long                        sClassIDs[ 30 ];
  58.         static CreatorFuncT                sCreatorFunc[ 30 ];
  59.         static int                        sNumRegistered;
  60.  
  61.         void                            initSelf();
  62.         
  63.         unsigned short                    mFlags;
  64.  
  65.         nodeClass*                         mNext;
  66.         nodeClass*                         mPrev;    
  67.         nodeClass*                         mParent;        
  68.         
  69.         long                            mShallowCount;                        
  70.         long                            mDeepCount;            //    -1 if Dirty
  71.         
  72.         
  73.         
  74.         virtual void                    UpdateCounts( int inShallowChange );
  75.                 
  76.     protected:
  77.         nodeClass*                        mHead;
  78.         nodeClass*                        mTail;
  79.         
  80.         //    Access this enum to typecast this node                                
  81.         unsigned char                    mType;    
  82.             
  83.         static nodeClass*                CreateNode( long inClassID, nodeClass* inParent );
  84.  
  85.  
  86.             
  87.     public:    
  88.         
  89.                                         nodeClass();
  90.         //    Post:    Constructs a node and places the node at the tail of <inParentPtr>
  91.                                         nodeClass( nodeClass* inParentPtr );                
  92.  
  93.         //    Post:    Destroys this node and all sub items inside it
  94.         virtual                            ~nodeClass();
  95.         
  96.         inline unsigned char            GetType() const                                    { return mType;    }
  97.         
  98.         //    Post:    This is how nodeClass "knows" what kind of nodeClass to instantiate when it reads an ID from a stream.
  99.         static void                        RegisterNodeClass( long inID, CreatorFuncT inCreatorFunc );
  100.  
  101.  
  102.         //    Post:    Returns a random number from <min> to <max>, inclusive.
  103.         static long                     Rnd( long min, long max );
  104.  
  105.  
  106.         #ifdef EG_DEBUG
  107.         nodeClass*                        mNextDebug;
  108.         static nodeClass*                sFirstDebug;
  109.         static long                        sCacheHitsA;
  110.         static long                        sCacheHitsB;
  111.         static long                        sCacheTrysA;
  112.         static long                        sCacheTrysB;
  113.         static long                        sCacheHitsC;
  114.         static long                        sCacheTrysC;
  115.         static void                        DebugBreak();
  116.         #endif
  117.  
  118.         //    Post:    All sub nodes (at any depth) that are selected are deleted.  If a node is selected, its contents are placed at the same
  119.         //            level of this and this is then deleted.
  120.         virtual void                    DeleteSelected();
  121.         
  122.         inline void                        Select()                                        { mFlags = mFlags | 0x1;        }
  123.         inline void                        Unselect()                                        { mFlags = mFlags & 0xFFFE;        }
  124.         inline bool                        IsSelected() const                                { return mFlags & 0x1; }
  125.         void                            SetSelected( bool inIsSelected )                { if ( inIsSelected ) Select(); else Unselect(); }
  126.  
  127.  
  128.         
  129.         //    Post:    Allows client write access to various boolean flags.
  130.         //    Note:    If <inFlagNum> is < 1 or > 9, nothing occurs.            
  131.         void                            SetFlag( unsigned int inFlagNum, bool inVal );
  132.         
  133.         //    Post:    Allows client read access to various boolean flags.
  134.         //    Note:    If <inFlagNum> is < 1 or > 9, false is returned.        
  135.         bool                            GetFlag( unsigned int inFlagNum ) const;
  136.  
  137.         //    Post:    This node and all sub nodes (and their sub nodes, etc) are un/selected with <inSelected>.
  138.         void                            SetTreeSelected( bool inSelected );
  139.         
  140.         //    Post:    Returns an associated unique or hash for the node.  
  141.         //    Note:    This is how XList knows what order to sort nodes, if that option is enabled.
  142.         virtual long                    GetKey()                                        { return 0;                        }
  143.         
  144.         //    Post:    The node is detached from it's parent.  Obviously, the caller now assumes ownership of the node.
  145.         void                             detach();
  146.         
  147.         //    Post:    This node is inserted in <inPrevNode>'s parent list following <inPrevNode> in the list order
  148.         void                            insertAfter( nodeClass* inPrevNode );
  149.         
  150.         //    Post:    If <inAfterNode> <= 0, <inNodeToAdd> is added at this' head.
  151.         //            If 0 < <inAfterNode> <= deepCount(), <inNodeToAdd> is added after the <inAfterNode> item.
  152.         //            If <inAfterNode> > deepCount(), <inNodeToAdd> is added at this' tail.    
  153.         void                            insertAfter( long inAfterNode, nodeClass* inNodeToAdd );
  154.  
  155.         //     The following are useful for setting up loops, etc
  156.         inline nodeClass*                 GetNext() const                                    { return mNext;                    }
  157.         inline nodeClass*                 GetPrev() const                                    { return mPrev;                    }
  158.         inline nodeClass*                GetParent() const                                { return mParent;                }
  159.         inline nodeClass*                 GetTail() const                                    { return mTail;                    }
  160.         inline nodeClass*                 GetHead() const                                    { return mHead;                    }
  161.  
  162.         //    Post:    Returns the node following this heirarchaly.
  163.         //    Post:     The node returned will have <inCeiling> as a super-parent.
  164.         /*    Sample:              1                (leftward is the mHead)
  165.                             /    \
  166.                           2        6
  167.                         /    \
  168.                         3    4
  169.                             |
  170.                             5    
  171.                         
  172.             void f( nodeClass* ceiling ) {
  173.                 node = ceiling;
  174.                 while ( node != NULL ) {
  175.                     print( node );
  176.                     node = node -> NextInChain( ceiling )
  177.                 }
  178.             }
  179.             
  180.             Output of f(1):    2, 3, 4, 5, 6                                    
  181.             Output of f(2):    3, 4, 5                        */
  182.         nodeClass*                        NextInChain( const nodeClass* inCeiling ) const;
  183.         
  184.         //    Post:    The inverse fcn of NextInChain()  (see above)
  185.         nodeClass*                        PrevInChain( const nodeClass* inCeiling ) const;
  186.         
  187.         //    Post:    <inPtr> is detached from it's current parent list and is inserted as the last node in this' sub list
  188.         void                             addToTail( nodeClass* inPtr );
  189.         
  190.         //    Post:    <inPtr> is detached from it's current parent list and is inserted at the 1st node in this' sub list
  191.         void                             addToHead( nodeClass* inPtr );
  192.         
  193.         //    Post:    Returns the last deep sub node in the deep sub list.
  194.         //            In other words, this fcn equals: this -> findSubNode( this -> deepCount() )
  195.         nodeClass*                        GetDeepTail() const;
  196.         
  197.         //    Post:    Returns the highest parent, say p, of this node where (p -> GetDeepTail() == this) is true. 
  198.         //            In other words, this returns the highest parent that has prev node.
  199.         //    Note:    Returns NULL if no such parent exists.
  200.         nodeClass*                        GetParentDeepTail( const nodeClass* inCeiling ) const;
  201.         
  202.         //    Post:    this -> CountDepth( GetParentDeepTail( inCeiling ) );
  203.         //            Or, in easy terms, CountOverhang returns the difference in depth between itself
  204.         //            and the parent node where CountOverhang is zero.
  205.         //            Or, easier yet, 
  206.         /*            1                    
  207.                     |- 2                2 -> CountOverhang( 1 ) == 0
  208.                     |  |-3              3 -> CountOverhang( 1 ) == 0
  209.                     |  |-4                4 -> CountOverhang( 1 ) == 1
  210.                     |
  211.                     |- 5                5 -> CountOverhang( 1 ) == 0
  212.                     |  |-6                6 -> CountOverhang( 1 ) == 1
  213.                     |    |-7            7 -> CountOverhang( 1 ) == 2
  214.                     |- 8                8 -> CountOverhang( 1 ) == 1                */
  215.         int                                CountOverhang( const nodeClass* inCeiling ) const;
  216.  
  217.         //    Post:    Used by a GUI to refine a given insertion point.
  218.         //    Post:    <ioNodeNum> and <ioDepth> may be adjusted/corrected.
  219.         //    Note:    Depths are such that 0 means root level.
  220.         //    Note:    Fcn succesful iff <true> is returned.
  221.         virtual bool                    CheckInsertPt( long& ioNodeNum, long& ioDepth );
  222.  
  223.         //    Post:    Mirrors a GUI drag of the selected items dropped before cell <inAboveCell> at depth <inDepth>
  224.         //    Note:    If <inDepth> is invalid or <inAboveCell> < 0 or > N, the closest boundry is used.
  225.         //    Calls:    VerifyNode()
  226.         virtual void                    MoveSelected( long afterItemNum, long inDepth );
  227.         
  228.         //    Post:    Examines <nodeAdded> to see if it's in a valid location.  If not, it may be moved or deleted.
  229.         virtual void                    VerifyNode( nodeClass* nodeAdded );
  230.         
  231.         //    Post:    Delete's all sub nodes in this node
  232.         virtual void                     deleteContents();
  233.         
  234.         //    Post:    Travels upward in its hierarchy until it finds a parent without its own parent
  235.         nodeClass*                        getHighestParent();
  236.                 
  237.         //    Post:    Returns <true> if <inMaybeParent> is any parent of this.
  238.         //    Note:    If inMaybeParent == NULL, false is returned.
  239.         bool                            HasTheParent( const nodeClass* inMaybeParent ) const;
  240.         
  241.         //    Post:    Returns <true> if this node contains other nodes  (optimized for speed)
  242.         inline bool                        IsEmpty() const                                 { return mHead == NULL;        }
  243.         
  244.         //    Post:    Returns the number of nodes in this node's sub list (in contrast to deepCount() )
  245.         inline long                        shallowCount() const                            { return mShallowCount;        }
  246.         
  247.         //    Post:    Returns the total number of nodes in this node's sub list PLUS the number of items in *their* sub lists.
  248.         long                            deepCount();
  249.         
  250.         //    Post:    Returns the number of super lists above this node. Ex, if this node didn't have a parent, countDepth()
  251.         //            would return 0.  If we then put it inside a newly constructed node, countDepth() would return 1.
  252.         long                            CountDepth( const nodeClass* inCeiling ) const;
  253.         
  254.         //    Post:    Return what node number this node is in its parent's shallow list.  Ex, if you added this node to the head of
  255.         //            another node, findInstance() would return a 1.  If this node is not in a sub list (ie, it has no parent), 
  256.         //            a 0 is returned.
  257.         long                            findInstance() const;
  258.         
  259.         //    Post:    Returns the <inNodeNum>th node in this node's (shallow) sub list. A NULL is returned if <inNodeNum>
  260.         //            is less than or equal to zero or if greater than the number of items in this node's sub list.
  261.         nodeClass*                        findNodeNum( long inNodeNum );
  262.  
  263.         //    Post:    Similar to findNodeNum( long ) except that the node returned is the <inNodeNum>th node in the _entire_
  264.         //            _sub_ _tree_ (as opposed to the base sub level).  If we had 2 sub nodes per node and we had 3 levels of
  265.         //            these, there would be a total of 2^3 leaves and a total of 2^4-1 nodes.  findSubNode( 8 ) would return the
  266.         //            second node at the root level.  The inverse of this function is findSubNode( nodeClass* ) and findNum(). 
  267.         //    Note:    If <inNodeNum> does not exist (ie, it's <= 0 or > deepCount()) then NULL is returned.
  268.         virtual nodeClass*                findSubNode( long inNodeNum );
  269.                     
  270.         //    Post:    This is the exact inverse function of findSubNode( long ). This fcn returns the deep instance number of <inNodePtr>
  271.         //            in this node deep sub tree.  If the node was not found in this node's sub tree, 0 is returned.
  272.         //    Note:    If <inNodePtr> is NULL, 0 is returned.
  273.         virtual long                    findSubNode( nodeClass* inNodePtr );
  274.  
  275.         //    Post:    All sub nodes in <sourceList> are appended in order inside this node.  If <inPutAtHead> is true, the nodes
  276.         //            in <sourceList> are put at the head of this, and if it is false, the nodes are put at the tail of this.
  277.         void                            absorbContents( nodeClass* sourceList, int inPutAtHead = true );
  278.  
  279.         //    Post:    All sub nodes in <sourceList> are moved to the tail of this if they are marked
  280.         void                            absorbMarked( nodeClass* sourceList );
  281.         
  282.         //    Post:    All sub nodes in <sourceList> are moved after this node (thus placing them in this node's parent's sub list)    
  283.         void                            absorbAfter( nodeClass* sourceList );
  284.  
  285.         //    Post:    Randomizes all sub nodes within this node.        
  286.         void                            RandomizeSubs();
  287.         
  288.         virtual void                    WriteTo( CEgOStream* inStream );
  289.         virtual void                    ReadFrom( CEgIStream* inFile );
  290.         virtual void                    StartRead( CEgIStream* inFile );
  291.  
  292. };
  293.  
  294.  
  295.  
  296. template <class T> class TNodeRegistrar {
  297.  
  298.     public:
  299.         static T*                        CreateFromStream( nodeClass* inParent ) {
  300.                                               return new T( inParent );
  301.                                            }
  302.  
  303.  
  304.         static void                        RegisterNode( long inClassID ) {
  305.                                              nodeClass::RegisterNodeClass( inClassID, (CreatorFuncT) CreateFromStream );
  306.                                            }
  307. };
  308.  
  309.  
  310. #endif
  311.  
  312.